package com.chen.blue.exception;

import com.auth0.jwt.exceptions.TokenExpiredException;
import com.chen.blue.constant.HttpStatus;
import com.chen.blue.exception.e.*;
import com.chen.blue.result.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolationException;

/**
 * Created By CLT On 2023/10/26.
 */
@SuppressWarnings("all")
@Slf4j
@RestControllerAdvice
public class GlobalException {

    /**
     * 处理所有异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public R handlerAllException(Exception e) {
        e.printStackTrace();
        return R.faild(HttpStatus.SYS_ERROR.getCode(), HttpStatus.SYS_ERROR.getDesc());
    }

    /**
     * 重复提交
     *
     * @param e
     * @return
     */
    @ExceptionHandler(NoRepeatException.class)
    public R handlerNoRepeatException(NoRepeatException e) {
        return R.success(HttpStatus.C429.getCode(), HttpStatus.C429.getDesc());
    }

    /**
     * 参数异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(DtoNullException.class)
    public R handlerDtoNullException(DtoNullException e) {
        return R.success(e.getMessage());
    }

    /**
     * 参数异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public R handlerHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        return R.faild(HttpStatus.C400.getCode(), HttpStatus.C400.getDesc());
    }

    /**
     * 资源找不到
     *
     * @param e
     * @return
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public R handlerNoHandlerFound(NoHandlerFoundException e) {
        return R.faild(HttpStatus.C404.getCode(), HttpStatus.C404.getDesc());
    }

    /**
     * 请求方法不支持
     *
     * @param e
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public R handlerMethodNotSupport(HttpRequestMethodNotSupportedException e) {
        return R.faild(HttpStatus.C405.getCode(), HttpStatus.C405.getDesc());
    }

    /**
     * 请求类型不支持
     *
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public R handlerHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        return R.faild(HttpStatus.C415.getCode(), HttpStatus.C415.getDesc());
    }

    /**
     * 用户不存在
     *
     * @param e
     * @return
     */
    @ExceptionHandler(UserNameNullException.class)
    public R handlerUserNameNotFound(UserNameNullException e) {
        return R.faild(HttpStatus.C404.getCode(), e.getMessage());
    }

    /**
     * 密码错误
     *
     * @param e
     * @return
     */
    @ExceptionHandler(PasswordErrorException.class)
    public R handlerPasswordError(PasswordErrorException e) {
        return R.faild(HttpStatus.C404.getCode(), e.getMessage());
    }

    /**
     * 处理参数校验
     *
     * @param e
     * @return
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public R handlerMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error("{}", e.getMessage());
        return R.faild(HttpStatus.C405.getCode(), e.getBindingResult().getAllErrors().stream().findFirst().get().getDefaultMessage());
    }

    /**
     * 处理集合中对象的参数校验
     *
     * @param e
     * @return
     */
    @ExceptionHandler({ConstraintViolationException.class})
    public R handlerConstraintViolationException(ConstraintViolationException e) {
        String message = e.getMessage();
        message = message.substring(message.indexOf(":") + 2, message.length() - 1);
        return R.faild(HttpStatus.C405.getCode(), message);
    }

    /**
     * 处理token异常
     *
     * @return
     */
    @ExceptionHandler({TokenExpiredException.class})
    public R handlerTokenExpiredException(TokenExpiredException e) {
        return R.faild(HttpStatus.C405.getCode(), e.getMessage());
    }

    /**
     * 处理权限不足
     *
     * @param e
     * @return
     */
    @ExceptionHandler(AccessDeniedException.class)
    public R handlerAccessDeniedException(AccessDeniedException e) {
        return R.faild(HttpStatus.C403.getCode(), HttpStatus.C403.getDesc());
    }

    /**
     * 账户被禁用
     *
     * @param e
     * @return
     */
    @ExceptionHandler(AccountOffException.class)
    public R handlerAccountOffException(AccountOffException e) {
        return R.faild(HttpStatus.C405.getCode(), e.getMessage());
    }

    /**
     * 内置角色不可删除
     *
     * @param e
     * @return
     */
    @ExceptionHandler(NoDeleteException.class)
    public R handlerNoDeleteException(NoDeleteException e) {
        return R.faild(HttpStatus.C405.getCode(), e.getMessage());
    }

    /**
     * 文件上传大小限制
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public R handlerMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
        return R.faild(HttpStatus.C405.getCode(), "单次文件大小不超过50M");
    }

    /**
     * 参数类型错误
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public R handlerMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
        return R.faild(HttpStatus.C400.getCode(), HttpStatus.C400.getDesc());
    }

}
